//
// Created by DELL on 2021/3/11.
//

#ifndef SYLAR_IOMANAGER_H
#define SYLAR_IOMANAGER_H

#include "scheduler.h"
#include "timer.h"
namespace sylar {
    class IOManager : public Scheduler, public TimerManager {
    public:
        using ptr = std::shared_ptr<IOManager>;
        using RWMutexType = RWMutex;
        enum Event {
            /// 无事件
            NONE = 0x0,
            /// 读事件(EPOLLIN)
            READ = 0x1,
            /// 写事件(EPOLLOUT)
            WRITE = 0x4
        };
    private:
        /*
         * Socket事件上下文类
         */
        struct FdContext {
            using MutexType = Mutex;
            /*
             * 事件上下文类
             */
            struct EventContext {
                /// 事件执行的调度器
                Scheduler *scheduler;
                /// 事件协程
                Fiber::ptr fiber;
                /// 事件的回调函数
                std::function<void()> cb;
            };
            EventContext& getEventContext(Event event);
            void resetContext(EventContext& ctx);
            void triggerEvent(Event event);
            /// 读事件上下文
            EventContext read;
            /// 写事件上下文
            EventContext write;
            /// 事件关联的句柄
            int fd = 0;
            /// 当前的事件
            Event events = NONE;
            /// 事件的Mutex
            MutexType mutex;
        };
    public:
        explicit IOManager(size_t threads = 1, bool use_caller = true, const std::string &name = " ");

        ~IOManager();

        // 1 success, -1 error
        int addEvent(int fd, Event event, std::function<void()> cb = nullptr);

        bool delEvent(int fd, Event event);

        bool cancelEvent(int fd, Event event);

        bool cancelAll(int fd);

        static IOManager *GetThis();

    protected:
        void tickle() override;

        bool stopping() override;

        void idle() override;

        void contextResize(size_t size);
        void onTimerInsertedAtFront() override;
        bool stopping(uint64_t &timeout);

    private:
        /// epoll 文件句柄
        int m_epfd = 0;
        /// pipe 文件句柄
        int m_tickleFds[2];
        /// 当前等待执行的事件数量
        std::atomic<size_t> m_pendingEventCount = {0};
        /// IOManager的Mutex
        RWMutexType m_mutex;
        /// socket事件上下文的容器
        std::vector<FdContext *> m_fdContexts;
    };


}
#endif //SYLAR_IOMANAGER_H
